<?php
/**
 * Created by PhpStorm.
 *
 * @Date: 2017-08-17
 * @Time: 16:39
 * @Author: cdkay
 * @Email: network@iyuanma.net
 *
 * @File： Buy.php
 */
namespace app\api\controller;

use app\api\model\user\Users;
use app\common\lib\pay\ApplePay;
use app\common\model\ApiResponse;
use app\common\controller\Base;
use app\common\lib\pay\PayFactory;
use app\common\model\BuyBill;
use app\common\model\UserCreditRecord;
use app\common\model\RealNameAuthentication;
use think\Db;
use think\Exception;
use think\exception\HttpResponseException;
use think\Log;
use think\Request;

class Buy extends Base {

    private $uid;

    public function __construct(Request $request = null) {

        $this->uid = checkUserToken(true);

        parent::__construct($request);

    }

    /**
     * 支付订单接口，获取支付所需参数签名
     *
     * @param Request $request
     * @return ApiResponse
     */
    public function order(Request $request) {

        $form = $this->getAndCheckForm([
            ['item_type', 'require|integer', '购买类型不能为空',],
            ['item_id', 'require|integer', '购买对象id不能为空',],
            ['pay_method', 'integer', '支付方式不能为空',],
            ['client_type', 'require|integer', '客户端类型不能为空',],
            ['trade_way', '^[1-2]$', '交易方式不正确',],
        ]);
        $trade_way = intval($form['trade_way'] ?? BuyBill::TRADE_WAY_ONLINE);
        $pay_method = intval($form['pay_method'] ?? 0);

        // 检查已购买
        if (BuyBill::checkBought($form['item_type'], $this->uid, $form['item_id'])) {
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED, '您已经购买了');
        }

        // 检查商品
        $item = BuyBill::getBuyInfo($form['item_type'], $this->uid, $form['item_id']);
        if (empty($item)) {
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'购买的商品不存在');
        }
        if (PayFactory::APPLEPAY == $form['pay_method']) {
            if (isset($item['apple_pay_price'])) {
                $item['price_orig'] = $item['price'] = $item['apple_pay_price'];
            }
        }
        $price = round($item['price'], 2);
        if ($price < 0.01) {
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'支付金额不正确');
        }

        // 下订单
        $orderNo = BuyBill::generateOrderNo($this->uid);
        $data = [
            'order_no' => $orderNo,
            'pay_amount' => $item['price'],
        ];
        try{

            Db::startTrans();

            if (BuyBill::TRADE_WAY_ONLINE == $trade_way) {
                // 获取支付方式
                $pay = PayFactory::getPayInstance($pay_method);
                if (empty($pay)) {
                    return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED, '未支持的支付方式');
                }
                // 产生支付订单
                $re = $pay->unifiedOrder($orderNo, $item['price'], '掌乾财经-'.$item['title'],
                    $form['client_type'], $request->ip(), $item['detail'], $form['ext']??null);

                $data[$pay->getKey()] = $re;
            }

            // 创建内部购买订单
            $bill = new BuyBill();
            $bill->bill_no =  $orderNo;
            $bill->bill_user =  $this->uid;
            $bill->bill_item_type =  $form['item_type'];
            $bill->bill_item_id =  $form['item_id'];
            $bill->bill_source =  $form['client_type'];
            $bill->bill_pay_amount =  $item['price'];
            $bill->bill_pay_method =  $pay_method;
            $bill->bill_payable_amount =  $item['price_orig'];
            $bill->bill_item_title =  $item['title'];
            $bill->bill_item_detail =  $item['detail'];
            $bill->bill_createtime =  time();
            $bill->bill_trade_way =  $trade_way;
            $bill->bill_type =  BuyBill::BILL_TYPE_CASH_PAY;
            $bill->credit_cost =  0;
            if (isset($item['gifts'])) $bill->gifts = $item['gifts'];
            $bill->save();

            Db::commit();

            $data['bill_id'] = $bill->bill_id;
            $data['create_time'] = $bill->bill_createtime;
            $data['have_paid'] = false;
            return ApiResponse::success($data);
        }catch (HttpResponseException $ex) {
            throw $ex;
        } catch (\Exception $ex){

            Db::rollback();
            if ($ex->getCode() == 405) {
                return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,$ex->getMessage());
            }

            Log::error($ex->getMessage());
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED, '创建订单失败');
        }
    }

    /**
     * 创建订单
     * @version v1.4+
     *
     * @return ApiResponse
     */
    public function order_submit() {
        $form = $this->getAndCheckForm([
            ['item_type', 'require|integer', '购买类型不能为空',],
            ['item_id', 'require|integer', '购买对象id不能为空',],
        ]);
        $item_type = intval($form['item_type']);
        $item_id = intval($form['item_id']);

        // 检查已购买
        if (BuyBill::checkBought($item_type,$this->uid,$item_id)) {
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'您已经购买了');
        }

        // 检查已有订单
        $bill = BuyBill::getExistsItem($item_type, $this->uid, $item_id);
        if ($bill) {
            return ApiResponse::success($bill->simpleInfo());
        }

        // 检查商品
        $item = BuyBill::getBuyInfo($item_type, $this->uid, $item_id);
        if (empty($item)) {
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'购买的商品不存在');
        }

        $price = round($item['price'], 2);
        if ($price < 0.01) {
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'支付金额不正确');
        }

        // 创建订单
        $bill = new BuyBill();
        $bill->bill_no =  BuyBill::generateOrderNo($this->uid);
        $bill->bill_user =  $this->uid;
        $bill->bill_item_type =  $item_type;
        $bill->bill_item_id =  $item_id;
        $bill->bill_pay_amount =  $item['price'];
        $bill->bill_payable_amount =  $item['price_orig'];
        $bill->bill_item_title =  $item['title'];
        $bill->bill_item_detail =  $item['detail'];
        $bill->bill_createtime =  time();
        $bill->bill_trade_way =  BuyBill::TRADE_WAY_ONLINE;
        $bill->bill_type =  BuyBill::BILL_TYPE_CASH_PAY;
        $bill->credit_cost =  0;
        if (isset($item['gifts']))
            $bill->gifts = $item['gifts'];
        if (isset($item['apple_pay_production_id']))
            $bill->apple_pay = BuyBill::applePayObject($item['apple_pay_price'],$item['apple_pay_production_id']);
        $bill->save();
        $bill = BuyBill::get($bill->bill_id);

        return ApiResponse::success($bill->simpleInfo());
    }

    /**
     * 获取订单支付参数
     * @version v1.4+
     *
     * @param Request $request
     * @return ApiResponse
     */
    public function order_pay(Request $request) {
        $form = $this->getAndCheckForm([
            ['bill_id', 'require|integer', '订单id不能为空',],
            ['pay_method', 'require|integer', '支付方式不能为空',],
            ['client_type', 'require|integer', '客户端类型不能为空',],
        ]);
        $bill = BuyBill::get(['bill_id'=>$form['bill_id'],'bill_user'=>$this->uid]);
        if (empty($bill)) {
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'订单不存在');
        }
        if ($bill->bill_have_paid) {
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'重复支付');
        }

        $pay = PayFactory::getPayInstance($form['pay_method']);
        if (empty($pay)) {
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED, '未支持的支付方式');
        }

        try{
            Db::startTrans();

            $data = [
                'order_no' => $bill->bill_no,
                'pay_amount' => $bill->bill_pay_amount,
                'bill_id' => $bill->bill_id,
                'create_time' => $bill->bill_createtime,
                'apple_pay' => $bill->apple_pay,
            ];

            $bill->bill_source =  $form['client_type'];
            $bill->bill_pay_method = $form['pay_method'];
            // 产生支付订单
            $res = $pay->unifiedOrder($bill->bill_no, $bill->bill_pay_amount, $bill->bill_item_title,
                $bill->bill_source, $request->ip(), $bill->bill_item_detail, $form['ext']??null);
            $data[$pay->getKey()] = $res;

            $bill->save();
            Db::commit();

            return ApiResponse::success($data);
        }catch (\Exception $ex){
            Db::rollback();
            if ($ex->getCode() == 405) {
                return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,$ex->getMessage());
            }
            Log::error($ex->getMessage());
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED, '获取订单失败');
        }
    }


    /**
     * 积分兑换商品
     * 需要商品支持积分兑换
     *
     * @return ApiResponse
     */
    public function credit_exchange() {

        $form = $this->getAndCheckForm([
            ['item_type', 'require|integer', '购买类型不能为空',],
            ['item_id', 'require|integer', '购买对象id不能为空',],
            ['client_type', 'require|integer', '客户端类型不能为空',],
        ]);
        $itemType = intval($form['item_type']);
        $itemId = intval($form['item_id']);

        // 检查已购买
        if (BuyBill::checkBought($itemType, $this->uid, $itemId)) {
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED, '您已经购买了');
        }

        // 检查商品
        $item = BuyBill::getBuyInfo($itemType, $this->uid, $itemId);
        if (empty($item)) {
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'购买的商品不存在');
        }

        if (!isset($item['enable_pay_type']) || !isset($item['credit_cost'] ) ||
            BuyBill::PAY_TYPE_CREDIT != $item['enable_pay_type'] || $item['credit_cost'] <= 0) {
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'该商品不支持积分兑换');
        }
        $credit_cost = intval($item['credit_cost']);

        $me = Users::get($this->uid);
        if ($me->credit < $credit_cost) {
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'对不起！您的积分不足，不能兑换！');
        }

        // 生成订单
        $orderNo = BuyBill::generateOrderNo($this->uid);
        try{
            Db::startTrans();

            // 创建内部购买订单
            BuyBill::create([
                'bill_no' => $orderNo,
                'bill_user' => $this->uid,
                'bill_item_type' => $itemType,
                'bill_item_id' => $itemId,
                'bill_source' => $form['client_type'],
                'bill_pay_amount' => 0,
                'bill_pay_method' => 0,
                'bill_payable_amount' => $item['price_orig'],
                'bill_item_title' => $item['title'],
                'bill_item_detail' => $item['detail'],
                'bill_createtime' => time(),
                'bill_trade_way' => BuyBill::TRADE_WAY_ONLINE,
                'bill_type' => BuyBill::BILL_TYPE_CREDIT_EXCHANGE,
                'credit_cost' => $item['credit_cost'],
            ]);
            $bill = BuyBill::get(['bill_no' => $orderNo]);

            Users::consumeCredit($me->id,UserCreditRecord::CHANGE_TYPE_EXCHANGE, intval($item['credit_cost']),
                '兑换'.BuyBill::getBuyItemName($itemType), ['bill_id' => $bill->bill_id]);

            $bill->successPay();

            Db::commit();
            return ApiResponse::success();
        }catch (Exception $ex){
            Db::rollback();
            Log::error("兑换失败：".$ex->getCode().' => '.$ex->getMessage());
            return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'兑换失败，可能是网络超时');
        }

    }

    /**
     * 支付成功调用
     * 苹果专用
     *
     * @return ApiResponse
     */
    public function apple_notify() {

        $this->iOSVerify();

        $order_no = input('post.order_no');
        $receipt = input('post.receipt');
        $bill = BuyBill::get(['bill_no' => $order_no,'bill_user'=>$this->uid]);
        if (empty($bill)) {
            ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'订单不存在');
        }

        if ($bill->chkBought()) {
            Log::error($bill->bill_id.'有重复的购买');
            ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'重复的购买');
        }

        $result = ApplePay::getInstance()->verifyReceipt($receipt);
        if ($result->success == false) {
            ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED, $result->errorMessage);
        }

        $bill->pay_trade_no = $receipt;
        $bill->bill_source = 1;
        $bill->bill_pay_method = PayFactory::APPLEPAY;
        if ($result->isSandbox) {
            $bill->is_sandbox = true;
            // 沙盒环境，可以什么也不做
            if (ApplePay::isSandboxServer()) {
                // 服务器配置了测试环境，可以处理
                $bill->successPay();
            }
        } else {
            // 生产环境，更新订单信息
            $bill->successPay();
        }

        return ApiResponse::success();
    }

    /**
     * 查询订单是否成功完成
     *
     * @return ApiResponse
     */
    public function check_order() {

        $form = $this->getAndCheckForm([
            ['order_no', 'require',],
        ]);

        $orderNo = $form['order_no'];

        $re = Db::table('buy_bill')
            ->where('bill_no','=', $orderNo)
            ->where('bill_user','=', $this->uid)
            ->field('bill_have_paid')
            ->find();

        return ApiResponse::success([
            'success' => $re['bill_have_paid'] ?? false,
        ]);
    }

    /**
     * confirm_bill
     * 确认订单
     *
     * @author zhengkai
     * @date 2018-02-27
     * @version v1.3.2
     *
     * @return ApiResponse
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function confirm_bill()
    {
        $form = $this->getAndCheckForm([
            ['goods_type', 'require|integer', '商品类型不能为空'],
            ['goods_id', 'require|integer', '商品id不能为空'],
        ]);

        $result = BuyBill::confirmBill($form['goods_type'], $form['goods_id']);
        if (is_null($result)) return ApiResponse::error(ApiResponse::ERR_RESOURCE_NON,'商品不存在');

        return ApiResponse::success($result);
    }


    /**
     * 我的购买订单
     * @return ApiResponse
     */
    public function my_bill() {

        $uid = checkUserToken(true);

        $form = $this->getAndCheckForm([
            ['rows', 'integer',],
            ['page', 'integer',],
        ]);

        $rows = intval($form['rows'] ?? 10);
        $re = BuyBill::myBill($uid, $rows, intval($form['page'] ?? 1), $this->isPC(), $form['status']??'');

        return ApiResponse::success($re['list'],$re['total'],$rows);
    }

    /**
     * bill_detail
     * 订单详情
     *
     * @author zhengkai
     * @date 2018-02-24
     *
     * @return ApiResponse
     */
    public function bill_detail()
    {
        $uid = checkUserToken(true);
        $form = $this->getAndCheckForm([
            ['bill_id', 'require|integer', '订单id不能为空'],
        ]);

        $result = BuyBill::billDetail($uid, $form['bill_id']);
        if (is_null($result)) return ApiResponse::error(ApiResponse::ERR_RESOURCE_NON,'无效订单');

        return ApiResponse::success($result);
    }
    /**
     * getOrderContract
     * 获取订单合同数据
     *  cc 2018-10-30
     * @return ApiResponse
     */
    public function getOrderContract()
    {
        $uid = checkUserToken(true);
        $form = $this->getAndCheckForm([
            ['bill_id', 'require|integer', '订单id不能为空'],
        ]);

        $result = BuyBill::contractData($uid, $form['bill_id']);

        if (is_null($result))
        return ApiResponse::error(ApiResponse::ERR_RESOURCE_NON,'无效订单');

        return ApiResponse::success($result);
    }

    /**
     * cancel_bill
     * 取消订单
     *
     * @author zhengkai
     * @version 1.3.2
     * @date 2018-02-26
     *
     * @return ApiResponse
     */
    public function cancel_bill()
    {
        $uid = checkUserToken(true);
        $form = $this->getAndCheckForm([
            ['bill_id', 'require|integer', '订单id不能为空'],
        ]);

        $bill = BuyBill::get($form['bill_id']);
        if (empty($bill)) return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'订单不存在');
        if ($bill->bill_have_paid) return ApiResponse::error(ApiResponse::ERR_OPERATE_FAILED,'已完成订单不能取消');
        $bill->delete();

        return ApiResponse::success();
    }


    /**
     * 我的推广用户的购买订单
     * @return ApiResponse
     *
     * @todo v1.4.1废弃
     */
    public function my_agency_bill() {

        $uid = checkUserToken(true);

        $form = $this->getAndCheckForm([
            ['month', 'require|date',],
            ['rows', 'integer',],
            ['page', 'integer',],
        ]);

        $re = BuyBill::myAgencyBill($uid, $form['month'],
            intval($form['rows']??10), intval($form['page']??1), $this->isPC());

        if ($this->isPC()) $re['last_page'] = intval(ceil($re['total'] / ($form['rows']??10)));
        return ApiResponse::success($re);
    }


}
